﻿using System.Text.Json.Serialization;
using Core.Caching;
using Core.Domain.Entities;
using Core.Domain.Enums;
using Core.Domain.ValueObjects;
using Core.Helpers;
using Core.Identity.Common.Interfaces.Common.Interfaces;
using Core.Identity.Menus.Caching;
using Core.Models;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Core.Identity.Menus.Features.Commands.Create;

/// <summary>
/// 创建菜单
/// </summary>
public class CreateMenuCommand : ICacheInvalidatorRequest<Result<Guid>>
{
    /// <summary>
    /// 编码
    /// </summary>
    public required string Code { get; set; }
    /// <summary>
    /// 名称
    /// </summary>
    public required string Name { get; set; }
    /// <summary>
    /// 分组
    /// </summary>
    public string? Group { get; set; }
    /// <summary>
    /// 父级菜单Id
    /// </summary>
    public Guid? ParentId { get; set; }
    /// <summary>
    /// 菜单元数据
    /// </summary>
    public required MenuMeta Meta { get; set; }
    /// <summary>
    /// 设置描述
    /// </summary>
    public string? Description { get; set; }
    /// <summary>
    /// 设置启用/禁用
    /// </summary>
    public bool Enabled { get; set; }

    /// <summary>
    /// 权限作用域
    /// </summary>
    public PermissionScope Scope { get; set; }

    [JsonIgnore]
    public string CacheKey => MenusCacheKey.GetAllCacheKey;

    [JsonIgnore]
    public IEnumerable<string>? Tags => MenusCacheKey.Tags;
}

public class CreateMenuCommandHandler(IIdentityDbContext dbContext) : IRequestHandler<CreateMenuCommand, Result<Guid>>
{

    public async Task<Result<Guid>> Handle(CreateMenuCommand request, CancellationToken cancellationToken)
    {
        var menu = await dbContext.Permissions
            .FirstOrDefaultAsync(x => x.Code == request.Code && request.Meta.MenuType == 3, cancellationToken);
        ExceptionHelper.ThrowIfNotNull(menu, "菜单编码已存在");

        menu = Permission.Create(
            request.Code,
            request.Name,
            request.Meta,
            request.ParentId,
            request.Group);

        menu.Sort = request.Meta.Rank;
        menu.Description = request.Description;
        menu.ChangeScope(request.Scope);

        await dbContext.Permissions.AddAsync(menu);

        var result = await dbContext.SaveChangesAsync(cancellationToken) > 0;
        return await Result<Guid>.SucceedAsync(result, menu.Id, ["创建失败"]);
    }
}
